package com.cyb.myfriend.service.impl;
import java.util.Date;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cyb.myfriend.constant.StatusCode;
import com.cyb.myfriend.domain.enums.TeamStatusEnum;
import com.cyb.myfriend.domain.request.TeamJoinRequest;
import com.cyb.myfriend.domain.request.TeamQuitRequest;
import com.cyb.myfriend.domain.entity.Team;
import com.cyb.myfriend.domain.entity.User;
import com.cyb.myfriend.domain.entity.UserTeam;
import com.cyb.myfriend.exception.BusinessException;
import com.cyb.myfriend.mapper.TeamMapper;
import com.cyb.myfriend.service.TeamService;
import com.cyb.myfriend.service.UserTeamService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

/**
* @author 78570
* @description 针对表【team(队伍)】的数据库操作Service实现
* @createDate 2024-08-27 17:11:42
*/
@Service
public class TeamServiceImpl extends ServiceImpl<TeamMapper, Team>
    implements TeamService {

    @Resource
    private TeamMapper teamMapper;

    @Resource
    private UserTeamService userTeamService;

    @Override
    public int saveTeam(Team team) {
        // 1.校验参数是否为空
        if (team == null || team.getTeamName().isEmpty()) {
            throw new BusinessException(StatusCode.NULL_PARAMS, "传入参数为空！");
        }
        // 如果队伍为加密状态，确认密码是否传入
        if (team.getStatus() == 2 && team.getPassword() == null) {
            throw new BusinessException(StatusCode.PARAMS_ERROR, "加密队伍，密码不能为空！");
        }
        //  2.创建队伍
        int insertResult = teamMapper.insert(team);
         // 3.返回
        return insertResult;
    }

    @Override
    public Integer updateTeam(Long userId, Team team) {
        //1.参数是否为空
        if (userId == null || team == null) {
            throw new BusinessException(StatusCode.NULL_PARAMS, "参数为空！");
        }
        //3.查询队伍是否存在
        Team teamSelect = teamMapper.selectById(team.getId());
        if (teamSelect == null) {
            throw new BusinessException(StatusCode.PARAMS_ERROR, "队伍不存在！");
        }
        //2.修改队伍的用户是否为队长
        if (team.getUserId() != userId) {
            throw new BusinessException(StatusCode.NO_AUTH, "没有权限！");
        }
        //4.如果队伍状态修改为加密，必须要有密码
        if (team.getStatus() == 2 && team.getPassword() == null) {
            throw new BusinessException(StatusCode.PARAMS_ERROR, "加密队伍，密码不能为空!");
        }
        //5,修改队伍
        int updateResult = teamMapper.updateById(team);
        return updateResult;
    }

    @Override
    public List<Team> searchTeamByTeamName(String teamName) {
        // 1.参数是否为空
        if (teamName == null) {
            throw new BusinessException(StatusCode.NULL_PARAMS);
        }
        // 2.查询队伍
        QueryWrapper<Team> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("teamName", teamName);
        List<Team> teamList = teamMapper.selectList(queryWrapper);
        // 3.脱敏返回
        return teamList.stream().map(this::getSafeTeam).collect(Collectors.toList());
    }

    /**
     * 脱敏
     *
     * @param team
     * @return
     */
    private Team getSafeTeam(Team team) {
        Team safeTeam = new Team();
        safeTeam.setId(team.getId());
        safeTeam.setTeamName(team.getTeamName());
        safeTeam.setDescription(team.getDescription());
        safeTeam.setStatus(team.getStatus());
        safeTeam.setUserId(team.getUserId());
        safeTeam.setMaxNum(team.getMaxNum());
        safeTeam.setUpdateTime(team.getUpdateTime());
        return safeTeam;
    }

    @Override
    public boolean joinTeam(TeamJoinRequest teamJoinRequest, User loginUser) {
        if (teamJoinRequest == null) {
            throw new BusinessException(StatusCode.PARAMS_ERROR);
        }
        Long teamId = teamJoinRequest.getTeamId();
        Team team = getTeamById(teamId);
        Integer status = team.getStatus();
        TeamStatusEnum teamStatusEnum = TeamStatusEnum.getEnumByValue(status);
        if (TeamStatusEnum.PRIVATE.equals(teamStatusEnum)) {
            throw new BusinessException(StatusCode.PARAMS_ERROR, "禁止加入私有队伍");
        }
        String password = teamJoinRequest.getPassword();
        if (TeamStatusEnum.SECRET.equals(teamStatusEnum)) {
            if (StringUtils.isBlank(password) || !password.equals(team.getPassword())) {
                throw new BusinessException(StatusCode.PARAMS_ERROR, "密码错误");
            }
        }
        // 该用户已加入的队伍数量
        long userId = loginUser.getId();
        System.out.println("getLock: " + Thread.currentThread().getId());
        QueryWrapper<UserTeam> userTeamQueryWrapper = new QueryWrapper<>();
        userTeamQueryWrapper.eq("userId", userId);
        long hasJoinNum = userTeamService.count(userTeamQueryWrapper);
        if (hasJoinNum > 5) {
            throw new BusinessException(StatusCode.PARAMS_ERROR, "最多创建和加入 5 个队伍");
        }
        // 不能重复加入已加入的队伍
        userTeamQueryWrapper = new QueryWrapper<>();
        userTeamQueryWrapper.eq("userId", userId);
        userTeamQueryWrapper.eq("teamId", teamId);
        long hasUserJoinTeam = userTeamService.count(userTeamQueryWrapper);
        if (hasUserJoinTeam > 0) {
            throw new BusinessException(StatusCode.PARAMS_ERROR, "用户已加入该队伍");
        }
        // 已加入队伍的人数
        long teamHasJoinNum = this.countTeamUserByTeamId(teamId);
        if (teamHasJoinNum >= team.getMaxNum()) {
            throw new BusinessException(StatusCode.PARAMS_ERROR, "队伍已满");
        }
        // 修改队伍信息
        UserTeam userTeam = new UserTeam();
        userTeam.setUserId(userId);
        userTeam.setTeamId(teamId);
        userTeam.setJoinTime(new Date());
        return userTeamService.save(userTeam);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean quitTeam(TeamQuitRequest teamQuitRequest, User loginUser) {
        if (teamQuitRequest == null) {
            throw new BusinessException(StatusCode.PARAMS_ERROR);
        }
        Long teamId = teamQuitRequest.getTeamId();
        Team team = getTeamById(teamId);
        long userId = loginUser.getId();
        UserTeam queryUserTeam = new UserTeam();
        queryUserTeam.setTeamId(teamId);
        queryUserTeam.setUserId(userId);
        QueryWrapper<UserTeam> queryWrapper = new QueryWrapper<>(queryUserTeam);
        long count = userTeamService.count(queryWrapper);
        if (count == 0) {
            throw new BusinessException(StatusCode.PARAMS_ERROR, "未加入队伍");
        }
        long teamHasJoinNum = this.countTeamUserByTeamId(teamId);
        // 队伍只剩一人，解散
        if (teamHasJoinNum == 1) {
            // 删除队伍
            this.removeById(teamId);
        } else {
            // 队伍还剩至少两人
            // 是队长
            if (team.getUserId() == userId) {
                // 把队伍转移给最早加入的用户
                // 1. 查询已加入队伍的所有用户和加入时间
                QueryWrapper<UserTeam> userTeamQueryWrapper = new QueryWrapper<>();
                userTeamQueryWrapper.eq("teamId", teamId);
                userTeamQueryWrapper.last("order by id asc limit 2");
                List<UserTeam> userTeamList = userTeamService.list(userTeamQueryWrapper);
                if (CollectionUtils.isEmpty(userTeamList) || userTeamList.size() <= 1) {
                    throw new BusinessException(StatusCode.SYSTEM_ERROR);
                }
                UserTeam nextUserTeam = userTeamList.get(1);
                Long nextTeamLeaderId = nextUserTeam.getUserId();
                // 更新当前队伍的队长
                Team updateTeam = new Team();
                updateTeam.setId(teamId);
                updateTeam.setUserId(nextTeamLeaderId);
                boolean result = this.updateById(updateTeam);
                if (!result) {
                    throw new BusinessException(StatusCode.SYSTEM_ERROR, "更新队伍队长失败");
                }
            }
        }
        // 移除关系
        return userTeamService.remove(queryWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteTeam(long id, User loginUser) {
        // 校验队伍是否存在
        Team team = getTeamById(id);
        long teamId = team.getId();
        // 校验你是不是队伍的队长
        if (team.getUserId() != loginUser.getId()) {
            throw new BusinessException(StatusCode.NO_AUTH, "无访问权限");
        }
        // 移除所有加入队伍的关联信息
        QueryWrapper<UserTeam> userTeamQueryWrapper = new QueryWrapper<>();
        userTeamQueryWrapper.eq("teamId", teamId);
        boolean result = userTeamService.remove(userTeamQueryWrapper);
        if (!result) {
            throw new BusinessException(StatusCode.SYSTEM_ERROR, "删除队伍关联信息失败");
        }
        // 删除队伍
        return this.removeById(teamId);
    }

    /**
     * 根据 id 获取队伍信息
     *
     * @param teamId
     * @return
     */
    private Team getTeamById(Long teamId) {
        if (teamId == null || teamId <= 0) {
            throw new BusinessException(StatusCode.PARAMS_ERROR);
        }
        Team team = this.getById(teamId);
        if (team == null) {
            throw new BusinessException(StatusCode.NO_TEAM);
        }
        return team;
    }

    /**
     * 获取某队伍当前人数
     *
     * @param teamId
     * @return
     */
    private long countTeamUserByTeamId(long teamId) {
        QueryWrapper<UserTeam> userTeamQueryWrapper = new QueryWrapper<>();
        userTeamQueryWrapper.eq("teamId", teamId);
        return userTeamService.count(userTeamQueryWrapper);
    }

}




